Assume build = 'build.rs' by default
authorPaul Woolcock <paul@woolcock.us>
Fri, 2 Dec 2016 03:42:45 +0000 (22:42 -0500)
committerPaul Woolcock <paul@woolcock.us>
Fri, 2 Dec 2016 19:57:03 +0000 (14:57 -0500)
This change makes cargo assume `build = "build.rs"` if there is a
`build.rs` file in the same directory as `Cargo.toml`. However, you
can set `build = false` to prevent this.

src/cargo/util/toml.rs

index 5e5dc93a669e86033d2afd05919b73fe72269bfe..1d4f8608ad08b0a9063471b50e82435632516d29 100644 (file)
@@ -286,12 +286,18 @@ pub struct TomlProfile {
     panic: Option<String>,
 }
 
+#[derive(RustcDecodable, Clone, Debug)]
+pub enum StringOrBool {
+    String(String),
+    Bool(bool),
+}
+
 #[derive(RustcDecodable)]
 pub struct TomlProject {
     name: String,
     version: TomlVersion,
     authors: Vec<String>,
-    build: Option<String>,
+    build: Option<StringOrBool>,
     links: Option<String>,
     exclude: Option<Vec<String>>,
     include: Option<Vec<String>>,
@@ -540,7 +546,11 @@ impl TomlManifest {
         }
 
         // processing the custom build script
-        let new_build = project.build.as_ref().map(PathBuf::from);
+        let manifest_file = util::important_paths::find_root_manifest_for_wd(None, &layout.root)
+                                 .chain_error(|| human("Could not find root manifest location"))?;
+        let base_dir = manifest_file.parent()
+                                    .ok_or(human("Could not get parent directory of manifest"))?;
+        let new_build = self.maybe_custom_build(&project.build, &base_dir);
 
         // Get targets
         let targets = normalize(&lib,
@@ -767,6 +777,23 @@ impl TomlManifest {
         }
         Ok(replace)
     }
+
+    fn maybe_custom_build(&self, build: &Option<StringOrBool>, project_dir: &Path)
+                          -> Option<PathBuf> {
+        let build_rs = project_dir.join("build.rs");
+        match *build {
+            Some(StringOrBool::Bool(false)) => None,        // explicitly no build script
+            Some(StringOrBool::Bool(true)) => Some(build_rs.into()),
+            Some(StringOrBool::String(ref s)) => Some(PathBuf::from(s)),
+            None => {
+                match fs::metadata(&build_rs) {
+                    Ok(ref e) if e.is_file() => Some(build_rs.into()),
+                    Ok(_) => None,
+                    Err(_) => None,
+                }
+            }
+        }
+    }
 }
 
 /// Will check a list of toml targets, and make sure the target names are unique within a vector.